#include "chartcostevol.h"
#include "main.h"
#include "pm/manager.h"
#include "pm/summary.h"
#include "pm/costevolution.h"

#include <wx/wxfreechartdefs.h>
#include <wx/chartpanel.h>
#include <wx/chart.h>
#include "wx/bars/barplot.h"
#include "wx/axis/numberaxis.h"
#include "wx/axis/categoryaxis.h"

#include <map>
#include <boost/foreach.hpp>

enum CostEvolSeries
{
	SERIE_WORK_REQUEST,
	SERIE_COST,
	SERIE_TASK,
	SERIES_COUNT
};

//{
// ****************************************************************************
//
// CostEvolDataset implementation
//
// ****************************************************************************

/**
 * \class CostEvolDataset
 */
class CostEvolDataset : public CategoryDataset
{
	pm::CostEvolution m_costEvol;
	double            m_workRequest;
	
public:
	CostEvolDataset();

	virtual double GetValue(int index, int serie);
	virtual int GetSerieCount();
	virtual wxString GetName(int index);
	virtual int GetCount();
	virtual wxString GetSerieName(int serie);
};

CostEvolDataset::CostEvolDataset()
{
	db::ID idProject = wxGetApp().GetActiveProject();
	
	pm::GetCostEvolutionByProject critEvol(idProject);
	pm::select(critEvol);
	m_costEvol = critEvol.m_evolution;
	
	pm::GetSummaryByProject critSummary(idProject);
	pm::select(critSummary);
	m_workRequest = critSummary.m_result.work_request();
}

double CostEvolDataset::GetValue(int index, int serie)
{
	switch (serie) {
	case SERIE_COST :
		return m_costEvol.get().at(index).cost;
		
	case SERIE_TASK :
		return m_costEvol.get().at(index).todo;
		
	case SERIE_WORK_REQUEST :
		return m_workRequest;
	}
	assert(false);
	return 0.0;
}

int CostEvolDataset::GetSerieCount()
{
	return SERIES_COUNT;
}

wxString CostEvolDataset::GetName(int index)
{
	return m_costEvol.get().at(index).month;
}

int CostEvolDataset::GetCount()
{
	return m_costEvol.get().size();
}

wxString CostEvolDataset::GetSerieName(int serie)
{
	return wxString::Format(wxT("Serie %i"), serie + 1);
}
//}

// ****************************************************************************
//
// CostEvolChart implementation
//
// ****************************************************************************

/**
 * CostEvolChart constructor
 */
CostEvolChart::CostEvolChart(wxWindow* parent)
: PanelChart(parent)
{
	wxTheApp->Connect(pmEVT_PROJECT_LOADED, wxCommandEventHandler(CostEvolChart::OnProjectLoaded), NULL, this);
	
	pmConnectNotify(pmEVT_COST_ADDED,   CostEvolChart::OnCostChanged);
	pmConnectNotify(pmEVT_COST_REMOVED, CostEvolChart::OnCostChanged);
	pmConnectNotify(pmEVT_COST_UPDATED, CostEvolChart::OnCostChanged);

	pmConnectNotify(pmEVT_TASK_ADDED,   CostEvolChart::OnCostChanged);
	pmConnectNotify(pmEVT_TASK_REMOVED, CostEvolChart::OnCostChanged);
	pmConnectNotify(pmEVT_TASK_UPDATED, CostEvolChart::OnCostChanged);
}

void CostEvolChart::UpdateChart()
{
	CategoryDataset* dataset = new CostEvolDataset();
	if (dataset->GetCount() == 0) {
		delete dataset;
		return;
	}
	
	BarType* barType = new LayeredBarType(20, 0);
	barType->SetBarArea(SERIE_WORK_REQUEST, new GradientAreaDraw(*wxBLACK_PEN, wxColour(50, 0,  0), wxColour(255, 0,   0)));
	barType->SetBarArea(SERIE_COST,         new GradientAreaDraw(*wxBLACK_PEN, wxColour(0, 50,  0), wxColour(0, 255,   0)));
	barType->SetBarArea(SERIE_TASK,         new GradientAreaDraw(*wxBLACK_PEN, wxColour(0,  0, 50), wxColour(0,   0, 255)));

	dataset->SetRenderer(new BarRenderer(barType));
	
	BarPlot* plot = new BarPlot();
	plot->AddDataset(dataset);
	
	CategoryAxis* bottomAxis = new CategoryAxis(AXIS_BOTTOM);
	bottomAxis->SetMargins(20, 20);
	plot->AddAxis(bottomAxis);
	plot->AddAxis(new NumberAxis(AXIS_LEFT));

	plot->LinkDataVerticalAxis(0, 0);
	plot->LinkDataHorizontalAxis(0, 0);

	SetChart(new Chart(plot));
}

void CostEvolChart::OnProjectLoaded(wxCommandEvent& event)
{
	event.Skip();
	UpdateChart();
}

void CostEvolChart::OnCostChanged(wxNotifyEvent& event)
{
	event.Skip();
	UpdateChart();
}
